
import getIn from './getIn';
import { FAIL } from './fail';
import { SUCCESS } from './success';
import { START } from './start';
import immutable from '../lib/immutable';
import dispatch from './dispatch';

/**
 * 处理列表的主要逻辑，支持分页读取，滚动列表拼接
 * @param fetch 调用的接口
 * @param callback 数据变动时通知外部刷新
 * @param option 初始配置[searchPath是设置获取列表数据的key路径，默认是读取返回结果的data.list，page是设置默认页码，rows是默认行数]
 */
export default function list(fetch, callback, option = { }) {
    const { page = 1, rows = 10, searchPath = ['data', 'list'], filter } = option;// 初始的页数和行数
    this.current = undefined;// 当前请求的标记
    this.querys = immutable.fromJS({});// 存放资料的地方
    this.prevQuerys = this.querys;
    this.setQuery = (nQuerys) => {
        this.prevQuerys = this.querys;
        this.querys = nQuerys;
        if (!immutable.is(this.querys, this.prevQuerys)) {
            callback && callback(this);
        }
    };
    this.loadMore = (option) => {
        this._loadData(true, option);
    };
    this.loadNew = (option) => {
        this._loadData(undefined, option);
    };
    this.loadPage = (option) => {
        this._loadData(undefined, option);
    };
    this._loadData = (isMore, option) => {
        let params = this.querys.getIn([this.current, 'params']) || immutable.fromJS({ page, rows });
        params = params.set('page', isMore ? params.get('page') + 1 : page);
        params = params.merge(option);// option的参数有最高的优先级
        // 不同参数的结果是不一样的，所以要防止数据之间互相覆盖，根据参数集创建唯一标记
        const flag = JSON.stringify(params);
        this.current = flag;// 标记当前
        fetch && (fetch(params, (f, fs) => {
            if (f === START) {
                this.setQuery(this.querys.setIn([flag, 'isLoading'], true).setIn([flag, 'params'], params));
            } else if (f === SUCCESS) {
                let _list = immutable.fromJS(getIn(fs, searchPath) || []);
                if (filter) {
                    _list = filter(_list);
                }
                this.setQuery(this.querys.removeIn([flag, 'isLoading'])
                    .setIn([flag, 'isLoaded'], true)
                    .setIn([flag, 'list'], _list)
                    .setIn([flag, 'hasNext'], _list.size > 0 && _list.size % params.get('rows') === 0)// 余数不为0 代表所有数据加载完毕
                    .setIn([flag, 'hasPrev'], params.get('page') > 1).setIn([flag, 'total'], fs.data.total));
            } else if (f === FAIL) {
                this.setQuery(this.querys.removeIn([flag, 'isLoading'])
                    .setIn([flag, 'isLoaded'], true));
            }
        }));
    };
    // 获取是否有下一页标记
    this.getHasNext = (paramsString = this.current) => this.querys.getIn([paramsString, 'hasNext']) || false;
    // 获取列表总数
    this.getTotal = (paramsString = this.current) => this.querys.getIn([paramsString, 'total']) || 0;
    // 获取是否有上一页标记
    this.getHasPrev = (paramsString = this.current) => this.querys.getIn([paramsString, 'hasPrev']) || false;
    // 获取是否加载完毕
    this.getIsLoaded = (paramsString = this.current) => this.querys.getIn([paramsString, 'isLoaded']) || false;
    // 获取是否加载中
    this.getIsLoading = (paramsString = this.current) => this.querys.getIn([paramsString, 'isLoading']) || false;
    this.getScrollList = (paramsString = this.current) => {
        let list = immutable.fromJS([]);
        const page = this.querys.getIn([paramsString, 'params', 'page']);
        const func = p => (v) => {
            if (immutable.is(p, v.get('params')) && v.get('list')) {
                list = list.concat(v.get('list'));
            }
        };
        for (let i = 1; i <= page; i++) {
            const p = this.querys.getIn([this.current, 'params']).set('page', i);
            this.querys.map(func(p));
        }
        return list.map((v, i) => v.set('index', i));
    };
    this.getParams = (keys, paramsString = this.current) => this.querys.getIn([paramsString, 'params', ...keys]);
    this.getPaginateList = (paramsString = this.current) => this.querys.getIn([paramsString, 'list']);
}
